﻿package com.spx;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UTFDataFormatException;

import android.app.Activity;
import android.app.Application;
import android.content.res.AssetManager;

/**
 * 字节数组流处理
 * @author Administrator
 * @see java.io.DataInputStream
 */
public class ArrayByteInput{
	private byte[] data;
	private int count;
	private static final String FS="/";
	private final static String assetsFlag="assets";
	
	public ArrayByteInput(byte[] data){
		this.data=data;
	}
	
	public ArrayByteInput(String resName)throws IOException{
		data=getDataSource(openResource(resName));
	}
	
	public ArrayByteInput(InputStream is) throws IOException{
		data=getDataSource(is);
	}
	
	/**
	 * 打开当前类加载器下的资源文件
	 * @param resName
	 * @return
	 * @throws IOException 
	 */
	private final static InputStream openResource(String resName) throws IOException{
		if(resName==null){
			return null;
		}
		final String tem=resName.startsWith(FS)?"":FS;
		final String fileName=assetsFlag+tem+resName;
		if(fileName.startsWith(assetsFlag)||fileName.startsWith(FS+assetsFlag)){
			boolean flag=fileName.startsWith(FS);
//			AssetManager asset=AndroidActivity.screenActivity.getAssets();
			//Application app = new Application();
			AssetManager asset=ApplicationContext.getAppContext().getAssets();
			String file;
			if(flag){
				file=fileName.substring(1);
			}else{
				file=fileName;
			}
			int index=file.indexOf(FS)+1;
			if(index!=-1){
				file=fileName.substring(index);
			}else{
				int length=file.length();
				int size=file.lastIndexOf(FS,0)+1;
				if(size<length){
					file=file.substring(size,length);
				}
			}
			return asset.open(file);
		}
		return resName.getClass().getResourceAsStream(resName);
	}
	
	/**
	 * 将InputStream转为byte[]
	 * @param is
	 * @return
	 * @throws IOException 
	 */
	final static private byte[] getDataSource(InputStream is) throws IOException{
		if(is==null){
			return null;
		}
		ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
		byte[] bytes=new byte[8192];
		try{
			int read;
			while((read=is.read(bytes))>=0){
				byteArrayOutputStream.write(bytes,0,read);
			}
			bytes=byteArrayOutputStream.toByteArray();
		}catch(IOException e){
			return null;
		}finally{
				if(byteArrayOutputStream!=null){
					byteArrayOutputStream.flush();
					byteArrayOutputStream=null;
				}
				if(is!=null){
					is.close();
					is=null;
				}
		}
		return bytes;
	}
	
	/**
	 * 可用大小
	 * @return
	 */
	private final int available(){
		return data.length-count;
	}

	private final void checkAvailable(int length) throws IOException{
		if(available()<length){
			throw new IOException("Lack of available sizes");
		}
	}

	/**
	 * 读取 byte 型数据流
	 * @return
	 * @throws IOException
	 */
	public final byte readByte() throws IOException{
		checkAvailable(1);
		return data[count++];
	}
	
	/**
	 * 读取 无符号byte 型数据流
	 * @return
	 * @throws IOException
	 */
	public final int readUByte() throws IOException{
		checkAvailable(1);
		return data[count++]&0xff;
	}
	
	/**
	 * 读取 无符号short 型数据流
	 */
	public final int readUShort()throws IOException{
		checkAvailable(2);
		return ((data[count++]&0xff)<<8)|(data[count++]&0xff);
	}
	
	public final int read(byte[] buffer) throws IOException{
		return read(buffer,0,buffer.length);
	}

	public final int read(byte[] buffer,int offset,int length) throws IOException{
		if(length==0){
			return 0;
		}
		checkAvailable(length);
		System.arraycopy(data,count,buffer,offset,length);
		count+=length;
		return length;
	}
	
	/**
	 * 读取 double 型数据流
	 */
	public void read(OutputStream out) throws IOException{
		out.write(data,count,data.length-count);
		count=data.length;
	}
	
	/**
	 * 读取 boolean 型数据流
	 */
	public final boolean readBoolean()throws IOException{
		return(readByte()!=0);
	}

	/**
	 * 读取 short 型数据流
	 */
	public final short readShort()throws IOException{
		checkAvailable(2);
		return (short)(((data[count++]&0xff)<<8)|(data[count++]&0xff));
	}

	/**
	 * 读取 int 型数据流
	 */
	public final int readInt()throws IOException{
		checkAvailable(4);
		return ((data[count++]&0xff)<<24)|((data[count++]&0xff)<<16)|((data[count++]&0xff)<<8)|(data[count++]&0xff);
	}
	
	/**
	 * 读取 long 型数据流
	 */
	public final long readLong()throws IOException{
		checkAvailable(8);
		return ((readInt()&0xffffffffL)<<32L)|(readInt()&0xffffffffL);
	}
	
	/**
	 * 读取 float 型数据流
	 */
	public final float readFloat()throws IOException{
		return Float.intBitsToFloat(readInt());
	}
	
	/**
	 * 读取 double 型数据流
	 */
	public final double readDouble()throws IOException{
		return Double.longBitsToDouble(readLong());
	}
	
	/**
	 * 读取 UTF-8字符串数据流
	 */
	public final String readUTF() throws IOException,UTFDataFormatException{
		checkAvailable(2);
		int utfLength=readShort()&0xffff;
		checkAvailable(utfLength);
		int goalPosition=count+utfLength;
		StringBuffer string=new StringBuffer(utfLength);
		while(count<goalPosition){
			int a=readByte()&0xff;
			if((a&0x80)==0){
				string.append((char)a);
			}else{
				int b=readByte()&0xff;
				if((b&0xc0)!=0x80){
					throw new UTFDataFormatException();
				}
				if((a&0xe0)==0xc0){
					char ch=(char)(((a&0x1f)<<6)|(b&0x3f));
					string.append(ch);
				}else if((a&0xf0)==0xe0){
					int c=readByte()&0xff;
					if((c&0xc0)!=0x80){
						throw new UTFDataFormatException();
					}
					char ch=(char)(((a&0x0f)<<12)|((b&0x3f)<<6)|(c&0x3f));
					string.append(ch);
				}else{
					throw new UTFDataFormatException();
				}
			}
		}
		return string.toString();
	}
	
	/**
	 * 读取数据流 到 指定Short数组
	 * @param array
	 * @param offset
	 * @param length
	 * @throws IOException
	 */
	public void readShortArray(short[] array,int offset,int length) throws IOException{
		for(int i=0;i<length;++i){
			array[offset+i]=readShort();
		}
	}

	/**
	 * 读取数据流 到 指定Int数组
	 * @param array
	 * @param offset
	 * @param length
	 * @throws IOException
	 */
	public void readIntArray(int[] array,int offset,int length) throws IOException{
		for(int i=0;i<length;++i){
			array[offset+i]=readInt();
		}
	}

	public final void close(){
		data=null;
		count=0;
		System.gc();
	}
	
	/**
	 * 获得系统InputStream流
	 * @return
	 */
	public final InputStream getInputStream(){
		return new java.io.ByteArrayInputStream(data);
	}
	
	public final byte[] getData(){
		return data;
	}
}
